#include "infoset.h"

#define ENABLE_UNIT_TEST 0
#define DEBUG_LEVEL 0

/* indexes:
 * 0 - real (reality) or sensor (creature)
 * 1..m - memory (former sensor data)
 * m+1..x - reasoning (not directly sensor data)
 */

InfoSet::InfoSet(EInfoId _iid)
	: iid(_iid)
{
	for(int i=0;i<I_SOURCE_TYPES;i++)
	{
		firstIndex[i] = IS_SOURCE_NOT_FOUND;
		sourceAmount[i] = 0;
	}
}


EInfoId InfoSet::id() const
{
	return iid;
}


int InfoSet::first(EInfoSource src)
{
	/* vector index. IS_SOURCE_NOT_FOUND if not found */
	return firstIndex[(int)src];
}

int InfoSet::amount(EInfoSource src)
{
	return sourceAmount[(int)src];
}

bool InfoSet::isEmpty() const
{
	return (infos.size() == 0);
}

void InfoSet::addInfo(Info& info)
{
	#if (DEBUG_LEVEL >= 1)
	std::cout << "INFOSET::addInfo: adding info (src="
	          << (int)info.source << ")" << std::endl;
	#endif
	#if (DEBUG_LEVEL >= 2)
	/* print sourcestartlist */
	for(int d=0;d<I_SOURCE_TYPES;d++)
		std::cout << "INFOSET::addInfo: before addition: src#" << d
			<< " start at " << first((EInfoSource)d)
			<< ", amount " << amount((EInfoSource)d) << std::endl;
	#endif
	
	/* add new info to infoset */
	std::vector<Info>::iterator iter = infos.begin();

	if (first(info.source) != IS_SOURCE_NOT_FOUND) {
	 	/* info of specified type already exists. Adding to end */
		iter += first(info.source) + amount(info.source);
		infos.insert(iter, info);
		sourceAmount[(int)info.source]++;
	}
	else {
		/* not found */
		#if (DEBUG_LEVEL >= 1)
			std::cout << "INFOSET::addInfo: not found of same source type" << std::endl;
		#endif
		int i_target=0;
		for(int i=0;i<info.source;i++) {
			i_target += sourceAmount[i];
		}
		iter += i_target;
		infos.insert(iter, info);
		sourceAmount[(int)info.source] = 1;
		firstIndex[(int)info.source] = i_target;
	}
	/* common */
	for(int i=(int)info.source+1; i<I_SOURCE_TYPES;i++)
		if (firstIndex[i] != IS_SOURCE_NOT_FOUND)
			firstIndex[i] ++;

	#if (DEBUG_LEVEL >= 2)
	/* print sourcestartlist */
	for(int d=0;d<I_SOURCE_TYPES;d++)
		std::cout << "INFOSET::addInfo: after addition: src#" << d
			<< " start at " << first((EInfoSource)d)
			<< ", amount " << amount((EInfoSource)d) << std::endl;
	#endif

} 

void InfoSet::toStream(std::ostream& os, unsigned int indent, ESerializationType sertype) const
{
	// different sertypes NOT YET IMPLEMENTED!!!
	Indent ind(indent), ind2(indent+2);
	os << ind << "ISET " << iidString(iid) << "{\n";
	for (unsigned int i=0;i<infos.size();i++) {
		os << ind2;
		os << infos[i];
		os << '\n';
	}
	os << ind << "}" << std::endl;
}


std::ostream& operator<<(std::ostream& os, const InfoSet& iset)
{
	iset.toStream(os);
	return os;
}




/* ------------------------- UNIT TEST PROGRAM --------------------------------- */

#if (ENABLE_UNIT_TEST >= 1)
/* test program for InfoSet-class */

int main(void)
{
	Info i1(true), i2(15), i3(4.332f); i2.source = isSense;
	std::cout << i1 << i2 << i3 << std::endl;

    InfoSet iset(i_spa_Position);
	iset.addInfo(i1);
	iset.addInfo(i2);
	iset.addInfo(i3);

	std::cout << iset << std::endl;
	
	return 0;
}

#endif
